#ifndef _EK_INTR_H_
#define _EK_INTR_H_

#include <kernel/kpipe.h>

/* The system level function prototype of irq interrupt handler */
typedef int(*irq_handler_t)(struct trapframe_t*);
/* and for exception handler */
typedef void(*ex_handler_t)(struct trapframe_t*);

/* Register handler for responding interrupt */
void register_ex_handler(uint32_t n, ex_handler_t h);
void register_irq_pipe(uint32_t irq, struct kpipe_t *pipe);
void register_irq_handler(uint32_t irq, irq_handler_t h);

/* A simple method to temporary enable/disable interrupt, used for
 * support multitasking when processingn system exceptions, etc. */

/*

  An example is shown:

  uint32_t flags = intr_disable_begin();

  ... (some codes which we want to execute without multitasking)

  intr_disable_end(flags);

*/
uint32_t intr_disable_begin(void);
void intr_disable_end(uint32_t eflags);
uint32_t intr_enable_begin(void);
void intr_enable_end(uint32_t eflags);

/* The possible count of all intrrupts */
#define IDT_COUNT 256
/* The low level func ptr table for irq */
extern uint32_t irq[16];
/* and for exception */
extern uint32_t isr[32];
/* handler for user's syscall request */
extern uint32_t syscall[];
/* user yield request */
extern uint32_t int_yield[];
/* ret entry for user exception handler */
extern uint32_t kcb_ret[];

/* The above four seem useless in kernel dev */


/* Use by intr.c, the func table for handling exception and irq
 * request */
extern ex_handler_t ex_handlers[32];
extern irq_handler_t irq_handlers[16];
extern struct kpipe_t *irq_pipes[16];
extern struct semaphore_t irq_semaphores[16];

void enable_irq_line(int numirq);
void disable_irq_line(int numirq);

/* Entry for exception */
void kexception(struct trapframe_t tf);
/* and for irq */
void kirq(struct trapframe_t tf);
/* the C entry of syscall */
void syscall_handler(struct trapframe_t tf);
/* the switching_trigger handler, which make multitasking possible */
void st_handler(uint32_t esp, struct trapframe_t tf);
/* and the after hook */
void after_switching_hook(struct trapframe_t tf);

/* page fault handler */
void pfhandler(struct trapframe_t *tf);

/* initialize the timer with specified frequency */
void timer_init(uint32_t freq);

/* make a irq0 call */
void call_irq0(void);

/* TODO -- tip missing */
int jump_user_pfhandler(uint32_t entry, uint32_t esp);

#endif /* _EK_INTR_H_ */
